/******************************************************************************
	This file is a part of the Snapshot Bioinformatics Project

	Copyright (C) 2012-2013 Jarom Schow

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
#ifndef PROGRESS_DLG_H
#define PROGRESS_DLG_H

#include <QtCore/QList>
#include <QtCore/QTime>

#include <QtWidgets/QDialog>

class QCheckBox;
class QLabel;
class QMutex;
class QProgressBar;
class QPushButton;
class QVBoxLayout;

class ProgressDlg : public QDialog {
	Q_OBJECT
public:

	ProgressDlg( QWidget *parent, const QString &title );
	~ProgressDlg();

	virtual bool	event( QEvent *e );

public slots:

	int		start( const QString &info, int totalSteps, bool canCancel, bool elaspeTime=false );
	void	pause();
	void	resume();
	void	cancel();
	void	finish( int progID );
	void	enable( bool onOff );

	void	setInfo( int progID, const QString &lbl );
	void	stepProgress( int progID, int steps );
	void	setProgress( int progID, int steps );
	void	reset( int progID );

	void	enableCancel( bool onOff );
	void	enableTimeElapsed( bool onOff );
	void	enableTimeEstimate( bool onOff );
	void	setAdditionalInfoWidget( QWidget *additionalInfo );

	bool		cancelEnabled() const;
	bool		timeElapsedEnabled() const;
	bool		timeEstimateEnabled() const;
	bool		isCanceled() const;
	bool		isActive() const;
	bool		isEnabled() const;
	QWidget*	getAdditionalInfoWidget() const;

public:

	int		progress( int progID ) const;
	int		totalSteps( int progID ) const;

signals:

	void			canceled();

protected:

	virtual void	timerEvent( QTimerEvent *e );
	virtual void	keyPressEvent( QKeyEvent *e );

private slots:

	void	step();
	void	cancelClicked();
	void	minimizeClicked();

private:

	void	refresh();
	void	needRefresh();
	int		getNextAvailableOp();
	void	setEstimate( int maximum, int current );
	QString	getTimeStr( int msec, bool estimate );
	void	doLayout();

	static const int	c_maxProgressOps = 3;

	enum ProgressFlags {
		Clean = 0x0000,
		DirtyValue = 0x0001,
		DirtyInfo = 0x0002,
		DirtyRange = 0x0004,
		DirtyVis = 0x0008,
		DirtySize = 0x0010,
		DirtyOptions = 0x0020,
		DirtyLayout = 0x0040,
		DirtyWidget = 0x0080,
		Dirty = 0xffff
	};

	struct ProgressOp {
		ProgressOp();

		bool			m_isActive;
		QLabel			*m_progressLabel;
		QProgressBar	*m_progressWgt;
		QString			m_info;
		int				m_tempSteps;
		int				m_curSteps;
		int				m_totalSteps;
		int				m_minSteps;
		int				m_refreshFlags;
		QTime			m_startTime;
		ProgressFlags	m_flags;
	};

	ProgressOp	m_progressOps[c_maxProgressOps];

	QMutex		*m_mutex;
	QEvent		*m_event;
	int			m_refreshFlags, m_timerId, m_minWidth, m_progressLevel;
	bool		m_isEnabled;
	QString		m_info;
	QWidget		*m_progressArea;
	QVBoxLayout	*m_progressAreaLyt;
	QLabel		*m_generalLabel, *m_estimateLbl, *m_elapsedLbl;
	QPushButton	*m_cancelBtn, *m_minimizeBtn;
	QTime		m_processTimer;
	int			m_time;
	bool		m_canceled, m_cancelEnabled, m_estimateEnabled, m_elapsedEnabled;
	QWidget		*m_infoWidget;
	QWidget		*m_nextInfoWidget;
	QTimer		*m_busyIndicatorTimer;
};

#endif // PROGRESS_DLG_H
